#include <kernel.h>
#include <pa4.h>

/*
 * Part B 1/1. dskschedule()
 * This function should be implemented to support each disk scheduling policy.
 * Parameters:
 *     ptr:     a descriptor of each device information
 *     option:  a disk scheduling policy to be used
 */

extern int currpid;
int DEBUG=1;

void findLastNode(disk_desc *ptr)
{
struct req_desc *iterator;
iterator=ptr->request_head;
//kprintf("Printing Queue: ");
               while(iterator!=NULL)
               {
		//kprintf(" %d ",iterator->block_no);
		iterator=iterator->next;
		}
//kprintf("\n");
//kprintf("LAst Node is: %d\n",iterator->block_no);

} 


int abs(int bks)
{
       if(bks>0)
               return bks;
       else
               return (bks*-1);
}

void dskschedule(disk_desc *ptr, int option) {

struct req_desc *iterator;
struct req_desc *tail;
struct req_desc *lb;
struct req_desc *prev;
struct req_desc *lprev;
int low=3255,diff=0,glow=3256;
tail = NULL;
lb = NULL;

prev = NULL;
lprev = NULL;

STATWORD ps;
	if(option==DISK_SCHED_FIFO)
	{
		return;
	}
	if((ptr->request_head==NULL)||((ptr->request_head)->next==NULL))
	{
		return;
	}

       if(option==DISK_SCHED_SSTF)
       {
       iterator=ptr->request_head;
               while(iterator!=NULL)
               {
                       diff=abs((ptr->head_sector-1)-iterator->block_no);
                       //kprintf("\n%d-%d-%d",ptr->head_sector-1,iterator->block_no,diff);
                       if(diff<low)
                       {
                       low=diff;
                       lb=iterator;
                       lprev=prev;
                       }

                       if(iterator->next==NULL)
                               tail=iterator;
                       prev=iterator;
                       iterator=iterator->next;
               }

               //kprintf("{%x %d}", lb, lb->block_no);
               if(lb == tail)
                       return;

               if(tail == lb && tail==(ptr->request_head-1))
                       return;

               if(lprev==NULL)
                       ptr->request_head=ptr->request_head->next;
               else
                       lprev->next=lb->next;

               tail->next=lb;
               tail=lb;
               lb->next=NULL;

               //kprintf("updated tail : %d",tail->block_no);
		findLastNode(ptr);
       }

	if(option==DISK_SCHED_CLOOK)
	{
	Bool found = FALSE;
	iterator=ptr->request_head;
	while(iterator!=NULL)
	{
		if(iterator->block_no >= ptr->head_sector  && 
			iterator->block_no < glow)
		{
			lprev = prev;
			lb = iterator;
			glow = iterator->block_no;
			found = TRUE;
		}
		if(iterator->next==NULL)
			tail = iterator;
		prev = iterator;
		iterator=iterator->next;
	}
	if(found==FALSE)
	{


		for(iterator = ptr->request_head,prev = NULL;iterator!=NULL;prev = iterator,iterator = iterator->next)
		{

			if(iterator->block_no < glow)
                        {
                                glow = iterator->block_no;
                                lb= iterator;
                                lprev = prev;
                        }

                        if(iterator->next==NULL)
                                tail=iterator;


		}


		
	}		

	if(ptr->request_head->next==NULL)
	{
		restore(ps);
      	        return;
	}

	if(lb == tail)
	{
		restore(ps);
	//	kprintf("ER  %d", tail->block_no);
       	return;
	}

       if(lprev==NULL)
               ptr->request_head=ptr->request_head->next;
       else
               lprev->next=lb->next;

      	tail->next=lb;
       tail=lb;
      	lb->next=NULL;
	restore(ps);
	}

//kprintf("\nCurrent Block : %d ",ptr->head_sector-1);
	

}
